/*****************************************Copyright(C)******************************************
******************************************* *********************************************
*------------------------------------------文件信息---------------------------------------------
* FileName          : modbus_master.h
* Author            : 张婷颖
* Version           : 1.0V
* Description       : 
*----------------------------------------历史版本信息-------------------------------------------
* History           :
* Description       :
*-----------------------------------------------------------------------------------------------
***********************************************************************************************/
#ifndef MODBUS_MASTER_H_
#define MODBUS_MASTER_H_
/* Includes-----------------------------------------------------------------------------------*/
#include "main.h"
#include "warper.h"
#include "top_scheme.h"

#if MODBUS | MODBUS_TCP                                                                                //使用modbus时使能
/* Private define-----------------------------------------------------------------------------*/

#define READ_ALL      1              //读取全部寄存器

#define FIXEDLEN     4               //最小帧字节数

//#define my_device_address  0x01      //本主站作为4G的从站设备地址
//#define COIL_SIZE          1000        //线圈大小
#define REGISTER_SIZE      4000      //寄存器大小
#define ONCE_REGISTER_SIZE 125       //一次最多读写寄存器
#define ONCE_COIL_SIZE     2000      //一次最多读写线圈个数
#define SEND_MAX           2         //请求最大次数


#define NON_INTERRUPT_PROCESS  1      //非中断处理接收数据
/* Private typedef----------------------------------------------------------------------------*/
typedef enum                         //主站状态
{
	START_REQUEST,
	FINISH,
	ABANDON_REQUEST,                 //超出重试次数，放弃请求
	FINISH_BREAK,                    //读取完成退出
}MASTER_STATUS_T;

typedef enum                         //功能码
{
	FUNCODE_01 = 0x01,
	FUNCODE_02,
	FUNCODE_03,
	FUNCODE_04,
	FUNCODE_05,
	FUNCODE_06,
	FUNCODE_0F = 0x0f,
	FUNCODE_10,

	ERRORCODE_01 = 0x81,             //异常功能码
	ERRORCODE_02,
	ERRORCODE_03,
	ERRORCODE_04,
	ERRORCODE_05,
	ERRORCODE_06,
	ERRORCODE_0F = 0x8f,
	ERRORCODE_10,

	NO_FUNCODE = 0xFF,
}FUNCODE_T;

typedef enum                            //异常码
{
	ILLEGA_FUNCODE = 0x01,             //非法功能码
	ILLEGA_ADDR,                       //非法数据地址
	ILLEGA_DATA,                       //非法数据
	DEVICE_ERROR,                      //设备错误
	DEVICE_COF,                        //设备确定，延长主站超时时间，正在处理，等待
	DEVICE_BUSY,                       //设备繁忙，延长超时时间
	DEVICE_REGATIVE_COF,               //设备否定确认，无法完成主站请求
	PARITY_ERROR,                      //存储奇偶差错，指示扩展文件区不能通过一致性检验

	NO_ERROR = 0xFF,
}EXCEPTION_CODE_T;

typedef struct                      //信息帧结构
{
	uint8_t device_address;         //设备地址    1字节
	uint16_t event_code;            //事务标识码 modbus tcp
	FUNCODE_T funcode;              //功能码      1字节
	uint8_t *pdata;                 //数据域数据  n字节
	uint16_t crc_info;              //CRC校验值   2字节
}FRAME_INFO;

typedef struct                      //发送帧数据域结构
{
	uint16_t buf_header_add;   		//寄存器首地址 2字节
	uint16_t buf_num;          		//写入/读取线圈或寄存器寄存器数量   2字节     最大125
	uint8_t data_len;               //写入/读取数据字节数
	uint16_t buf_rwdata[ONCE_REGISTER_SIZE];    	//写入/读取数据  1字节/2字节
//	uint16_t buf_sumnum;            //寄存器总数量 2字节
	EXCEPTION_CODE_T exception_code;//出现错误时的异常码
}M_DATA_INFO;

typedef struct
{
	uint16_t DEVICE_ADDRESS;                   //设备地址
	FRAME_INFO recvinfo;                       //recvinfo分解接收的帧
	FRAME_INFO txinfo;                         //txinfo 发送请求的帧信息
	M_DATA_INFO rx_data;                       //rx_data更详细分解数据帧
	M_DATA_INFO tx_data;                       //tx_data发送的请求帧信息
	uint16_t rebuf[REGISTER_SIZE];             //rebuf响应分解后的数据
	MASTER_STATUS_T master_status;             //modbus主站状态
	uint8_t send_count;                        //发送次数
	uint8_t read_finish;                       //读取完成标志位

}INFO_COMBINATION;

/* Private macro------------------------------------------------------------------------------*/

/* Private variables--------------------------------------------------------------------------*/
//extern uint8_t coil_state[COIL_SIZE];       //线圈状态
//extern uint16_t rebuf_into[REGISTER_SIZE];      //寄存器
//extern uint8_t read_finish;                     //读取完成标志位
/* Private function prototypes----------------------------------------------------------------*/

/* Private functions--------------------------------------------------------------------------*/
uint8_t M_Analyse_info(uint8_t *p, uint8_t Len, INFO_COMBINATION *sum_info);                        //分析接收到的信息帧

#if MODBUS_TCP
uint8_t M_Analyse_info_TCP(uint8_t *p,uint8_t Len,INFO_COMBINATION *sum_info);                     //分析接收到的信息帧 tcp
void M_achieves_read_TCP(uint16_t device_address,FUNCODE_T funcode,uint16_t buf_add,uint8_t num,INFO_COMBINATION *sum_top);                  //设置读取的命令
void M_achieves_write_TCP(uint16_t device_address,FUNCODE_T funcode,uint16_t buf_add,uint8_t num,uint16_t *buf, INFO_COMBINATION *sum_top);  //设置写入的命令
void M_ask_tx_data_TCP(FRAME_INFO *tx_info,M_DATA_INFO *tx_data_info,MASTER_STATUS_T *master_status);    //请求新的数据
void rerequest_TCP(INFO_COMBINATION *sum_info);                                                         //请求重发
#endif /*MODBUS_TCP*/

void refresh_info(INFO_COMBINATION *sum_info);                                                      //清除接收发送信息
void rerequest(INFO_COMBINATION *sum_info);                                                         //请求重发
void M_Dealwith(INFO_COMBINATION *sum_info);                                                        //处理对应功能码及应答
uint8_t M_check_code01_02(M_DATA_INFO *rx_data, M_DATA_INFO *tx_data, uint16_t *rebuf);             //检查响应功能码01 02--读线圈状态
uint8_t M_check_code03_04(M_DATA_INFO *rx_data, M_DATA_INFO *tx_data, uint16_t *rebuf);             //检查响应功能码03 04--读寄存器状态
uint8_t M_check_code05_06(M_DATA_INFO *rx_data, M_DATA_INFO *tx_data, uint16_t *rebuf);             //检查响应功能码05 06--写单个线圈/寄存器状态
uint8_t M_check_code0f_10(M_DATA_INFO *rx_data, M_DATA_INFO *tx_data, uint16_t *rebuf);             //检查响应功能码0f 10--写多个线圈/寄存器状态
void M_error_code(INFO_COMBINATION *sum_info);                                                      //异常处理
void M_achieves_read(uint16_t device_address,FUNCODE_T funcode,uint16_t buf_add,uint8_t num,INFO_COMBINATION *sum_top);                  //设置读取的命令
void M_achieves_write(uint16_t device_address,FUNCODE_T funcode,uint16_t buf_add,uint8_t num,uint16_t *buf, INFO_COMBINATION *sum_top);  //设置写入的命令
void M_ask_tx_data(FRAME_INFO *tx_info,M_DATA_INFO *tx_data_info,MASTER_STATUS_T *master_status);    //请求新的数据
void M_timeout(FRAME_INFO *tx_info,M_DATA_INFO *tx_data_info,uint8_t *send_count,MASTER_STATUS_T *master_status);                                   //响应超时处理函数

//void M_Dealwith(uint8_t *pdata);                                   //处理对应功能码及应答
//uint8_t M_check_code01_02(void);                                   //检查响应功能码01 02--读线圈状态
//uint8_t M_check_code03_04(void);                                   //检查响应功能码03 04--读寄存器状态
//uint8_t M_check_code05_06(void);                                   //检查响应功能码05 06--写单个线圈/寄存器状态
//uint8_t M_check_code0f_10(void);                                   //检查响应功能码0f 10--写多个线圈/寄存器状态
//void M_error_code(void);                                             //异常处理
//void M_achieves_read(FUNCODE_T funcode,uint16_t buf_add,uint8_t num);                //设置读取的命令
//void M_achieves_write(FUNCODE_T funcode,uint16_t buf_add,uint8_t num,uint16_t *buf);  //设置写入的命令

//void M_ask_tx_data(FRAME_INFO tx_info,M_DATA_INFO tx_data_info);  //请求新的数据
//void M_timeout(void);                                              //响应超时处理函数

//void test_read(void);                                              //测试读取
//void test_write(void);                                             //测试写入


#endif  /*MODBUS | MODBUS TCP*/

#endif /* MODBUS_MASTER_H_ */
